﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Fasterflect;
using Kugar.Core.Configuration;
using Kugar.Core.Exceptions;
using Kugar.Core.ExtMethod;
using Newtonsoft.Json.Linq;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;

namespace Kugar.Web.WechatMPOAuth
{
    /// <summary>
    /// 设置指定Controller或者Action调用微信公众号授权功能
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class WechatMPOAuthAttribute : AuthorizeAttribute
    {
        //private Type _handler = null;
        private IMPOAuthHandler _handler = null;
        private string _typeName = "";
        private string _assembly = "";
        private OAuthScope _scope = OAuthScope.snsapi_base;
        private string _callbackUrl;

        /// <summary>
        /// 初始化特性
        /// </summary>
        /// <param name="handlerType">设置用于处理授权的类,必须实现IMPOAuthHandler接口</param>
        /// <param name="scope">授权范围,默认为base</param>
        /// <param name="callbackUrl">回调的地址,如需更改,请检查对应的路由是否配置完成,回调的是MPOAuthCallbackController的Callback函数</param>
        public WechatMPOAuthAttribute(Type handlerType, OAuthScope scope = OAuthScope.snsapi_base,
            string callbackUrl = "Core/MPCallback/Callback")
        {
            _scope = scope;

            //_handler = handlerType ?? throw new ArgumentNullException(nameof(handlerType));

            if (handlerType==null)
            {
                throw new ArgumentNullException(nameof(handlerType));
            }

            if (string.IsNullOrEmpty(callbackUrl))
            {
                throw new ArgumentOutOfRangeException(nameof(callbackUrl));
            }

            _typeName = handlerType.Namespace + "." + handlerType.Name;
            _assembly = handlerType.Assembly.FullName;
            _handler = MPCallbackController.getMPHandler(_typeName);// ( IMPOAuthHandler)handlerType.CreateInstance();


            _callbackUrl = callbackUrl;
        }

        /// <summary>
        /// 授权检查
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var user = (WechatUserOAuth) filterContext.HttpContext.Session["WechatMPUser"];

            if (_handler.CheckAuthority(filterContext))
            {
                if (filterContext.Controller is IWechatMPOAuthController)
                {
                    ((IWechatMPOAuthController) filterContext.Controller).CurrentMPUser = user;
                }

                //base.OnAuthorization(filterContext);
            }
            else
            {
                //if (filterContext.Controller is IWechatMPOAuthController && (filterContext.Controller as IWechatMPOAuthController)?.CurrentMPUser != null)
                //{
                //    base.OnAuthorization(filterContext);
                //    return;
                //}
                //else 
                if (filterContext.ActionDescriptor.GetCustomAttributes(true)
                    .Any(x => x.GetType() == typeof(SkipWechatMPAuthorityAttribute)))
                {
                    //base.OnAuthorization(filterContext);
                    return;
                }

                base.OnAuthorization(filterContext);
            }
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            var backurl = filterContext.RequestContext.HttpContext.Request.RawUrl;
            var host = filterContext.RequestContext.HttpContext.Request.Url.Host;
            var port = filterContext.RequestContext.HttpContext.Request.Url.Port;

            //var handler = (IMPOAuthHandler) ;

            var mp = _handler.MPGetter(filterContext,filterContext.ActionDescriptor);

            var appID = mp.appID;
            var appserect = mp.appSerect;

            var json = new JObject()
                       {
                           ["BackUrl"] = backurl,
                           ["Scope"] = (int) _scope,
                           ["AppID"] = appID,
                           ["AppSerect"] = appserect
                       };

            var guid = Guid.NewGuid().ToStringEx();

            filterContext.HttpContext.Session[guid] = json;
            filterContext.HttpContext.Session[$"{guid}_handler"] = _typeName;
            filterContext.HttpContext.Session[$"{guid}_assembly"] = _assembly;

            if (!_callbackUrl.StartsWith("http", StringComparison.CurrentCultureIgnoreCase))
            {
                if (_callbackUrl[0]=='/')
                {
                    _callbackUrl = $"http://{host}{(port != 80 ? ":" + port : "")}{_callbackUrl}";
                }
                else
                {
                    _callbackUrl = $"http://{host}{(port != 80 ? ":" + port : "")}/{_callbackUrl}";
                }
            }

            var url = OAuthApi.GetAuthorizeUrl(appID, _callbackUrl, guid, _scope, "code");

            filterContext.Result = new RedirectResult(url);
        }
    }

    /// <summary>
    /// 跳过微信授权检查
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class SkipWechatMPAuthorityAttribute : Attribute
    {
    }
}